package pers.yurwisher.rubick.oauth2.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import pers.yurwisher.rubick.common.base.BaseController;
import pers.yurwisher.rubick.common.wrapper.R;
import pers.yurwisher.rubick.oauth2.security.OAuth2User;

import java.security.Principal;
import java.util.Map;

/**
 * @author yq 2021/4/19 11:20
 * @description OAuth2Controller
 */
@RestController
public class OAuth2Controller extends BaseController {

    @Autowired
    private TokenEndpoint tokenEndpoint;
    @Autowired
    private AuthorizationEndpoint authorizationEndpoint;
    @Autowired
    private ConsumerTokenServices consumerTokenServices;

    /**
     * token接口
     *
     * @param principal
     * @param parameters 密码模式 client_id, client_secret, grant_type:password, scope, username, password
     *                   <p>
     *                   刷新token模式 client_id, client_secret, grant_type:refresh_token, refresh_token
     *                   <p>
     *                   授权码模式 client_id, response_type:code, scope, redirect_uri, state
     *                   返回授权码,客户根据授权码再去获取access_token 需要参数 grant_type: authorization_code, code, redirect_uri
     *                   <p>
     *                   简化模式 与授权码模式类似不过回调后直接返回access_token
     */
    @PostMapping("/oauth/token")
    public R token(Principal principal, @RequestParam Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
        return R.ok(tokenEndpoint.postAccessToken(principal, parameters).getBody());
    }

    @GetMapping("/oauth/userInfo")
    public R userInfo(Principal principal) {
        OAuth2User oAuth2User = (OAuth2User) ((OAuth2Authentication) principal).getPrincipal();
        logger.info("user: {} ", principal);
        return R.ok(oAuth2User);
    }

    @PostMapping("/oauth/logout")
    public R<String> logout(@RequestHeader(value = "Authorization") String authorization) {
        String accessToken = authorization.substring(OAuth2AccessToken.BEARER_TYPE.length()).trim();
        consumerTokenServices.revokeToken(accessToken);
        return R.ok();
    }

    /**
     * 跳转统一认证页面
     *
     * @param which   哪个页面
     * @param display 布局 pc或者 mobile
     */
    @GetMapping("/login")
    public ModelAndView show(@RequestParam(required = false) String which, @RequestParam(required = false) String display) {
        logger.info("跳转认证页面 [{}] [{}]", which, display);
        return getShowView(which, display);
    }


    private ModelAndView getShowView(String which, String display) {
        return new ModelAndView("ftl/login");
    }
}
